#include "globalAPI.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "syber_popen.h"

#define MAC_SIZE 18
#define IP_SIZE 16

typedef struct {
    pthread_mutex_t cmdLock;
} Rb_lck_t;

static Rb_lck_t Rb_lck;

int Rb_mtx_init() { return pthread_mutex_init(&(Rb_lck.cmdLock), NULL); }

int Rb_mtx_cancel()
{
    pthread_mutex_destroy(&(Rb_lck.cmdLock));
    return 0;
}

void charToHexStringWithSpace(char *tag, unsigned char *buf, int len)
{
    int i = 0;
    printf("len is %d\n", len);
#if 1
    time_t t;
    struct tm *lt = NULL;
    time(&t);
    lt = localtime(&t);
#endif

    if (tag != NULL) {
        printf("%s(%d)| %04d-%02d-%02d %02d:%02d:%02d :", tag, len, lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec);
    }

    for (i = 0; i < len; i++) {
        printf("%02x ", buf[i]);
    }
    printf("\n");
}

int uint32ToCharBig(unsigned char buf[], int bufLen, uint32_t val)
{
    if (bufLen < 4)
        return -1;

    buf[0] = ((val >> 24) & 0xFF);
    buf[1] = ((val >> 16) & 0xFF);
    buf[2] = ((val >> 8) & 0xFF);
    buf[3] = ((val >> 0) & 0xFF);

    return 0;
}

int uint32ToCharLittle(unsigned char buf[], int bufLen, uint32_t val)
{
    if (bufLen < 4)
        return -1;

    buf[0] = ((val >> 0) & 0xFF);
    buf[1] = ((val >> 8) & 0xFF);
    buf[2] = ((val >> 16) & 0xFF);
    buf[3] = ((val >> 24) & 0xFF);

    return 0;
}

int uint16ToCharBig(unsigned char buf[], int bufLen, uint16_t val)
{
    if (bufLen < 2)
        return -1;

    buf[0] = ((val >> 8) & 0xFF);
    buf[1] = ((val >> 0) & 0xFF);

    return 0;
}

int uint16ToCharLitter(unsigned char buf[], int bufLen, uint16_t val)
{
    if (bufLen < 2)
        return -1;

    buf[1] = ((val >> 8) & 0xFF);
    buf[0] = ((val >> 0) & 0xFF);

    return 0;
}

int CharBigToInteger(unsigned char buf[], int bufLen, uint32_t *val)
{
    if (bufLen == 2) {
        *val = (buf[0] << 8) | buf[1];
    } else if (bufLen == 3) {
        *val = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
    } else if (bufLen == 4) {
        *val = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]);
    }

    return 0;
}

int CharLitterToInteger(unsigned char buf[], int bufLen, uint32_t *val)
{
    if (bufLen == 1) {
        *val = buf[0];
    } else if (bufLen == 2) {
        *val = (buf[1] << 8) | buf[0];
    } else if (bufLen == 3) {
        *val = (buf[2] << 16) | (buf[1] << 8) | (buf[0]);
    } else if (bufLen == 4) {
        *val = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | (buf[0]);
    }

    return 0;
}

int decStrLitterToInteger(unsigned char buf[], int bufLen, int *val)
{
    if (bufLen == 1) {
        *val = ((buf[0] >> 4) * 10) + (buf[0] & 0x0F);
    } else if (bufLen == 2) {
        *val = ((buf[1] >> 4) * 1000) + ((buf[1] & 0x0F) * 100) + ((buf[0] >> 4) * 10) + (buf[0] & 0x0F);
    }

    return 0;
}

uint8_t Ascii2Hex(unsigned char *ascii, uint8_t len, unsigned char *hex)
{
    int i        = 0;
    char chHex[] = "0123456789ABCDEF";

    char cmsb = 0;
    char clsb = 0;
    char c    = 0;

    for (i = 0; i < len; i++) {
        cmsb   = chHex[((uint8_t)ascii[i]) >> 4] - '0';
        clsb   = chHex[((uint8_t)ascii[i]) & 0x0f];
        c      = (clsb >= 'A') ? clsb - 'A' + 10 : clsb - '0';
        hex[i] = (cmsb << 4) | c;
        printf("%d:%x--%x--\n", i, cmsb, c);
    }

    hex[len] = '\0';

    return len;
}

void ascii_to_integer(unsigned char *str, unsigned char *des)
{
    int i   = 0;
    int len = 0;

    if (str == NULL)
        return;

    len = strlen((char *)str);

    for (i = 0; i < len; i++) {
        if (str[i] >= '0' && str[i] <= '9')
            *(des++) = str[i] - '0';
    }
}

uint8_t mon_day[2][12] = {{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
uint8_t Judeg_year(uint16_t year)
{
    if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400) == 0)
        return 0;  //闰年
    else
        return 1;
}

int SecToDate(uint32_t sec, dataTime *rtcDate)
{
    uint32_t yearcount;
    uint32_t daycount;
    uint32_t year = 0;
    uint32_t runy = 0, mounth = 0, day = 0, hour = 0, minutes = 0, second = 0;
    uint8_t temp1 = 0, week = 0;
    daycount  = sec / 86400;
    yearcount = daycount / 365;
    year      = 1970 + yearcount;
    runy      = ((year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400) - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400);
    daycount  = (daycount % 365) - runy;

    while (daycount > 28) {
        if (!Judeg_year(1970 + yearcount)) {
            if (daycount >= mon_day[1][temp1])
                daycount -= mon_day[1][temp1];
            else
                break;
        } else {
            if (daycount >= mon_day[0][temp1])
                daycount -= mon_day[0][temp1];
            else
                break;
        }
        temp1++;
    }
    mounth  = temp1 + 1;
    day     = daycount + 1;
    hour    = (sec % 86400) / 3600;
    minutes = ((sec % 86400) % 3600) / 60;
    second  = ((sec % 86400) % 3600) % 60;
    printf("data:%d-%d-%d\ntime:%d:%d:%d\n", year, mounth, day, hour, minutes, second);

    rtcDate->year = year;
    rtcDate->mon  = mounth;
    rtcDate->day  = day;
    rtcDate->hour = hour;
    rtcDate->min  = minutes;
    rtcDate->sec  = sec;

    if (year > 1970 && year < 2099) {
        if (mounth < 3) {
            mounth += 12;
            --year;
        }
        week = (day + 1 + 2 * mounth + 3 * (mounth + 1) / 5 + year + (year >> 2) - year / 100 + year / 400) % 7;
    }
    switch (week) {
        case 0:
            printf("Sunday\n");
            break;
        case 1:
            printf("Monday\n");
            break;
        case 2:
            printf("Tuesday\n");
            break;
        case 3:
            printf("Wednesday\n");
            break;
        case 4:
            printf("Thursday\n");
            break;
        case 5:
            printf("Friday\n");
            break;
        case 6:
            printf("Saturday\n");
            break;
        default:
            printf("error\n");
            break;
    }
    return 0;
}

uint32_t dateToSec(uint16_t year, uint8_t mon, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec)
{
    uint32_t countsec = 0;
    uint16_t i;
    uint8_t j;

    if (year > 1970 && year < 2099) {
        for (i = 1970; i < year; i++) {
            if (Judeg_year(i))
                countsec += 31536000;
            else
                countsec += 31622400;
        }
        mon -= 1;
        if (Judeg_year(year)) {
            for (j = 0; j < mon; j++) countsec += (mon_day[0][j] * 86400);
        } else {
            for (j = 0; j < mon; j++) countsec += (mon_day[1][j] * 86400);
        }
        day -= 1;
        countsec += day * 86400;
        countsec += hour * 3600;
        countsec += min * 60;
        countsec += sec;
        return countsec;
    }
    return countsec;
}

/* crc calculate */
uint16_t clareCalcCrc(unsigned char *data, unsigned len)
{
    uint32_t crc = 0;

    // charToHexStringWithSpace("crc msg",data,len);
    unsigned b;
    do {
        crc ^= ((uint32_t)(*data)) << 8;
        b = 8;
        do {
            crc <<= 1;
            if (crc & 0x10000)
                crc ^= 0x11021;
        } while (--b);
        data++;
    } while (--len);
    printf("---->crc:%x\n", (uint16_t)crc);
    return (uint16_t)crc;
}

typedef struct server_mac {
    unsigned char mac[6];
} MAC_t;

unsigned char macs[][6] =
    {{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}, {0x11, 0x25, 0x65, 0x48, 0x98, 0x76}, {0x11, 0x36, 0x98, 0x75, 0x27, 0x0B}, {0x11, 0x58, 0x96, 0x58, 0x74, 0x36}, {0x11, 0x77, 0x85, 0x96, 0x35, 0x78}, {0x58, 0x67, 0x7F, 0xD2, 0xD2, 0xD2}};

int getMacaddr(char mac[], int type)
{
    unsigned char macAddr[6]  = {0};
    unsigned char macClare[6] = {0x11, 0x77, 0x85, 0x96, 0x35, 0x78};
    // unsigned char macAlula[6] ={0x11,0x22,0x33,0x44,0x55,0x66};
    // unsigned char macAlula[6] = {0x11, 0x58, 0x96, 0x58, 0x74, 0x36};
    // unsigned char macAlula[6] = {0x11, 0x25, 0x65, 0x48, 0x98, 0x76};
    unsigned char macAlula[6] = {0};
    memcpy(macAlula, macs[2], 6);
    if (type == 1) {
        memcpy(macAddr, macClare, 6);
    } else {
        memcpy(macAddr, macAlula, 6);
    }

    // get_local_mac("wlan0", macAddr);

    memcpy(mac, macAddr, 6);
    printf("MAC build-> %x", mac[0]);
    return 0;
}

char *bitValOfChar(uint8_t bit, uint8_t val) { return ((val >> bit) & 0x01) ? "true" : "false"; }

char *bitVal(bool bit) { return (bit) ? "true" : "false"; }

void utcTime()
{
    time_t t;
    struct tm *lt = NULL;
    time(&t);
    lt = localtime(&t);

    printf("-----UTC time is:%d--------\n", dateToSec(lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec));
}

int get_ip_by_domain(const char *domain, char *ip)
{
    char **pptr          = NULL;
    struct hostent *hptr = NULL;

    hptr = gethostbyname(domain);
    if (NULL == hptr) {
        printf("gethostbyname error for host:%s\n", domain);
        return -1;
    }

    for (pptr = hptr->h_addr_list; *pptr != NULL; pptr++) {
        if (NULL != inet_ntop(hptr->h_addrtype, *pptr, ip, IP_SIZE)) {
            return 0;
        }
    }

    return -1;
}

int get_local_mac(const char *eth_inf, unsigned char *mac)
{
    struct ifreq ifr;
    int sd;

    bzero(&ifr, sizeof(struct ifreq));
    if ((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("get %s mac address socket creat error\n", eth_inf);
        return -1;
    }

    strncpy(ifr.ifr_name, eth_inf, sizeof(ifr.ifr_name) - 1);

    if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) {
        printf("get %s mac address error\n", eth_inf);
        close(sd);
        return -1;
    }

    /*
        snprintf(mac, MAC_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x",
                (unsigned char)ifr.ifr_hwaddr.sa_data[0],
                (unsigned char)ifr.ifr_hwaddr.sa_data[1],
                (unsigned char)ifr.ifr_hwaddr.sa_data[2],
                (unsigned char)ifr.ifr_hwaddr.sa_data[3],
                (unsigned char)ifr.ifr_hwaddr.sa_data[4],
                (unsigned char)ifr.ifr_hwaddr.sa_data[5]
        );
    */

    memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);

    close(sd);

    return 0;
}

int get_local_ip(const char *eth_inf, char *ip)
{
    int sd;
    struct sockaddr_in sin;
    struct ifreq ifr;

    sd = socket(AF_INET, SOCK_DGRAM, 0);
    if (-1 == sd) {
        printf("socket error: %s\n", strerror(errno));
        return -1;
    }

    strncpy(ifr.ifr_name, eth_inf, IFNAMSIZ);
    ifr.ifr_name[IFNAMSIZ - 1] = 0;

    // if error: No such device
    if (ioctl(sd, SIOCGIFADDR, &ifr) < 0) {
        printf("ioctl error: %s\n", strerror(errno));
        close(sd);
        return -1;
    }

    memcpy(&sin, &ifr.ifr_addr, sizeof(sin));
    snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));

    close(sd);
    return 0;
}

/*
**get continuous interval values
**
** [1][2]
*/
int getContinuInterval(uint8_t buf[], int len, int offset, uint8_t *startIndex, uint8_t *endIndex)
{
    int tmp = 0;
    int i   = 0;

    *startIndex = buf[offset];
    for (i = offset; i < len; i++) {
        tmp       = buf[i];
        *endIndex = buf[i + 1];
        if ((*endIndex - tmp) != 1) {
            *endIndex = tmp;
            break;
        }
    }
    return i + 1;
}

int shellCommand(char *cmd, char *reply, int reply_len, bool respone, bool wait)
{
    FILE *fp       = NULL;
    char pbuf[128] = {0};

    if (cmd == NULL) {
        return -1;
    }

    if (!strlen(cmd)) {
        return -2;
    }

    dzlog_info("shell cmd: \"%s\"", cmd);

    if (respone) {
        if (reply == NULL) {
            return -1;
        }

        fp = syber_popen(cmd, "r");
    } else {
        fp = syber_popen(cmd, "w");
    }

    if (NULL != fp) {
        while (respone && (fgets(pbuf, sizeof(pbuf) - 1, fp) != NULL)) {
            if ((strlen(reply) + strlen(pbuf)) > (reply_len - 1)) {
                memset(reply, 0, reply_len);
            }
            strncat(reply, pbuf, reply_len - 1);
            memset(pbuf, 0, sizeof(pbuf));
        }
        if (wait) {
            syber_pclose(fp, 0);
        } else {
            syber_pclose(fp, 1);
        }
        return 0;
    }

    return -1;
}

char *myStrtok;
char *redbee_strtok(char *s, const char *ct)
{
    char *sbegin = NULL, *send = NULL;
    sbegin = s ? s : myStrtok;
    if (!sbegin) {
        return NULL;
    }

    sbegin += strspn(sbegin, ct);
    if (*sbegin == '\0') {
        myStrtok = NULL;
        return (NULL);
    }

    send = strpbrk(sbegin, ct);
    if (send && *send != '\0')
        *send++ = '\0';

    myStrtok = send;
    return (sbegin);
}
